import sys
try:
    from suds.client import Client
except ImportError:
    sys.stderr.write('missing suds')
try:
    from xml2py import xml2py
except ImportError:
    sys.stderr.write('missing xml2py')

wsdl_services = {
    'cssm':'http://cssm.sasr.edu.au/axis/services/CSSM_MDC?wsdl',
    'jldg':'http://ws.jldg.org/axis/services/mdc?wsdl',
    'ldg': 'http://globe-meta.ifh.de:8080/axis/services/ILDG_MDC?wsdl',
    'ukqcd':'http://wennekers.epcc.ed.ac.uk:8080/axis/services/MetadataCatalogue?wsdl',
    'usqcd':'http://usqcd.fnal.org/mdc-service/services/ILDGMDCService?wsdl'
}

def domains():
    response = []
    for name,wsdl_service in wsdl_services.items():
        try:
            client = Client(wsdl_service)
            response.append((name,True))
        except:
            response.append((name,False))
    return response

def ensembles(domain='all'):
    ensembles = []
    for name,wsdl_service in wsdl_services.items():
        if domain in (name,None,'all'):
            try:
                client = Client(wsdl_service)
                s = client.service
                result = s.doEnsembleURIQuery("Xpath", "/markovChain", 0, -1)
                items = result['results']
                for qcduri in items or []:
                    ensembles.append(name+'/'+qcduri[5:])
            except IOError:
                pass
    return ensembles

class Ensemble(object):
    def __init__(self,path):
        self.domain = path.split('/',1)[0]
        self.qcduri = 'mc://'+path.split('/',1)[1]
        self.wsdl_service = wsdl_services.get(self.domain,None)
        if not self.wsdl_service:
            raise KeyError
        self.client = Client(self.wsdl_service)
        self.service = self.client.service
    def files(self):
        query = '/gaugeConfiguration/markovStep[markovChainURI="%s"]' % self.qcduri
        response = self.service.doConfigurationLFNQuery("Xpath", query, 0, -1)
        files = response['results'] or []
        return [fileuri.split('/')[-1] for fileuri in files]
    def info(self,filename=None,files=False):
        if not filename:
            xml = self.service.getEnsembleMetadata(self.qcduri)['document']
            if not xml: return {}
            info = xml2py(xml,strip=1)
            info['files'] = self.files()
            return info
        query = '/gaugeConfiguration/markovStep[markovChainURI="%s"]' % self.qcduri
        response = self.service.doConfigurationLFNQuery("Xpath", query, 0, -1)
        files = response['results']
        fileuri = [f for f in files if f.endswith('/'+filename)][0]
        xml = self.service.getConfigurationMetadata(fileuri)['document']
        return xml2py(xml,strip=1)

def import_all():
    import shelve
    storage = shelve.open('data.shelve')
    n=0
    for name,status in domains():
        print '[ON] ' if status else '[OFF]',name
        if not status: continue
        paths = ensembles(name)
        if 1:
            for k,path in enumerate(paths):
                path = path.encode('utf8')
                e=Ensemble(path)
                info = e.info(files=True)
                storage[path] = e.info()
                if k==0 and info['files']:
                    f = info['files'][0]
                    storage[path+'//'+f.encode('utf8')]=e.info(f)
                print name,n,path
                n+=1
            
def test():
    n=0
    for name,status in domains():
        print '[ON] ' if status else '[OFF]',name
        if not status: continue
        paths = ensembles(name)
        n+=len(paths)
        if False and paths:                    
            path = paths[0]
            e = Ensemble(path)
            info = e.info()
            files = e.files()
            print path,'contains',len(files),'files including',files[0]
            print e.file_info(files[0])
    print n

if __name__=='__main__': import_all()
